<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>20 Observable Operators - window, windowToggle, groupBy · ShaofeiZi Blog · 做个日常记录</title>
    <meta name="description" content="訾绍飞的博客。万物皆有裂缝处，那是光射进来的地方。">
    <link rel="shortcut icon" href="/BLOG/favicon.ico">
  <link rel="manifest" href="/BLOG/manifest.json">
  <meta name="theme-color" content="#3F51B5">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <link rel="apple-touch-icon" href="/BLOG/icons/192.png">
  <link rel="mask-icon" href="/BLOG/icons/safari-pinned-tab.svg" color="#3eaf7c">
  <meta name="msapplication-TileImage" content="/icons/192.png">
  <meta name="msapplication-TileColor" content="#3F51B5">
    
    <link rel="preload" href="/BLOG/assets/css/42.styles.90045bd1.css" as="style"><link rel="preload" href="/BLOG/assets/js/app.1a725be8.js" as="script"><link rel="preload" href="/BLOG/assets/js/14.5d9fcbf2.js" as="script"><link rel="prefetch" href="/BLOG/assets/js/7.88ba0bb7.js"><link rel="prefetch" href="/BLOG/assets/js/0.d3e592bd.js"><link rel="prefetch" href="/BLOG/assets/js/1.39b9c99c.js"><link rel="prefetch" href="/BLOG/assets/js/2.68dc10c9.js"><link rel="prefetch" href="/BLOG/assets/js/3.dfebdd5e.js"><link rel="prefetch" href="/BLOG/assets/js/4.ea97a821.js"><link rel="prefetch" href="/BLOG/assets/js/5.d8c2ecbf.js"><link rel="prefetch" href="/BLOG/assets/js/6.e51cd79c.js"><link rel="prefetch" href="/BLOG/assets/js/8.d9eebc06.js"><link rel="prefetch" href="/BLOG/assets/js/9.1a541d13.js"><link rel="prefetch" href="/BLOG/assets/js/10.4ec9ca67.js"><link rel="prefetch" href="/BLOG/assets/js/11.02558377.js"><link rel="prefetch" href="/BLOG/assets/js/12.d0e2086f.js"><link rel="prefetch" href="/BLOG/assets/js/13.5af02ddd.js"><link rel="prefetch" href="/BLOG/assets/js/15.ca0178b2.js"><link rel="prefetch" href="/BLOG/assets/js/16.cd99d056.js"><link rel="prefetch" href="/BLOG/assets/js/17.56f11c1d.js"><link rel="prefetch" href="/BLOG/assets/js/18.21837cc7.js"><link rel="prefetch" href="/BLOG/assets/js/19.73335fea.js"><link rel="prefetch" href="/BLOG/assets/js/20.1632ab79.js"><link rel="prefetch" href="/BLOG/assets/js/21.43175244.js"><link rel="prefetch" href="/BLOG/assets/js/22.5b7c0cca.js"><link rel="prefetch" href="/BLOG/assets/js/23.e624ba97.js"><link rel="prefetch" href="/BLOG/assets/js/24.ac5f7b41.js"><link rel="prefetch" href="/BLOG/assets/js/25.6934a11d.js"><link rel="prefetch" href="/BLOG/assets/js/26.407b2583.js"><link rel="prefetch" href="/BLOG/assets/js/27.7449d673.js"><link rel="prefetch" href="/BLOG/assets/js/28.52e25437.js"><link rel="prefetch" href="/BLOG/assets/js/29.fba21f3a.js"><link rel="prefetch" href="/BLOG/assets/js/30.2cd6d3e2.js"><link rel="prefetch" href="/BLOG/assets/js/31.0b0a749f.js"><link rel="prefetch" href="/BLOG/assets/js/32.92134487.js"><link rel="prefetch" href="/BLOG/assets/js/33.ad2b89cc.js"><link rel="prefetch" href="/BLOG/assets/js/34.9b22334e.js"><link rel="prefetch" href="/BLOG/assets/js/35.825f3d75.js"><link rel="prefetch" href="/BLOG/assets/js/36.cc3da84c.js"><link rel="prefetch" href="/BLOG/assets/js/37.8f339f62.js"><link rel="prefetch" href="/BLOG/assets/js/38.5674618f.js"><link rel="prefetch" href="/BLOG/assets/js/39.180f0d85.js"><link rel="prefetch" href="/BLOG/assets/js/40.275f26e3.js"><link rel="prefetch" href="/BLOG/assets/js/41.ce0f5927.js">
    <link rel="stylesheet" href="/BLOG/assets/css/42.styles.90045bd1.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div data-app="true" id="app" class="application theme--light"><div class="application--wrap"><div class="v-progress-linear blog-progress" style="height:3px;display:none;"><div class="v-progress-linear__background accent" style="height:3px;opacity:0.4;width:100%;"></div><div class="v-progress-linear__bar"><!----><div class="v-progress-linear__bar__determinate accent" style="width:0%;"></div></div></div><aside class="v-navigation-drawer v-navigation-drawer--close v-navigation-drawer--fixed v-navigation-drawer--is-mobile" style="height:100%;margin-top:0px;max-height:calc(100% - 0px);transform:translateX(-240px);width:240px;"><div><div class="aside-brand-wrap"><div class="aside-brand"><a href="/BLOG/" class="aside-avatar elevation-2 router-link-active"><img src="/BLOG/face.png" alt="avatar"></a><hgroup class="mt-3 variant-hide"><div class="subheading white--text">訾绍飞</div><a href="mailto:zishaofei221@gmail.com" title="zishaofei221@gmail.com" class="aside-mail primary--text text--lighten-5">zishaofei221@gmail.com</a></hgroup></div></div><hr class="v-divider theme--dark"><div class="v-list nav-list"><div class="secondary--text"><a href="/BLOG/" class="v-list__tile v-list__tile--link"><div class="v-list__tile__avatar"><div class="v-avatar" style="height:40px;width:40px;"><i class="fa fa-home"></i></div></div><div class="v-list__tile__content">首页</div></a></div><div class="secondary--text"><a href="/BLOG/tags" class="v-list__tile v-list__tile--link"><div class="v-list__tile__avatar"><div class="v-avatar" style="height:40px;width:40px;"><i class="fa fa-tag"></i></div></div><div class="v-list__tile__content">标签</div></a></div><div class="secondary--text"><a href="https://github.com/ShaofeiZi" target="_blank" class="v-list__tile v-list__tile--link"><div class="v-list__tile__avatar"><div class="v-avatar" style="height:40px;width:40px;"><i class="fab fa-github"></i></div></div><div class="v-list__tile__content">Github</div></a></div><div class="secondary--text"><a href="/BLOG/about" class="v-list__tile v-list__tile--link"><div class="v-list__tile__avatar"><div class="v-avatar" style="height:40px;width:40px;"><i class="fa fa-user-secret"></i></div></div><div class="v-list__tile__content">About</div></a></div></div></div><div class="v-navigation-drawer__border"></div></aside><nav class="blog-toolbar v-toolbar v-toolbar--fixed theme--dark primary" style="margin-top:0px;padding-right:0px;padding-left:0px;transform:translateY(0px);"><div class="v-toolbar__content" style="height:56px;"><button type="button" class="v-btn v-btn--icon"><div class="v-btn__content"><i class="fa fa-bars"></i></div></button><div class="v-toolbar__title">20 Observable Operators - window, windowToggle, groupBy</div><div class="spacer"></div><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""><!----></div><div class="v-menu" style="display:none;"><div class="v-menu__activator"><button type="button" class="v-btn v-btn--icon"><div class="v-btn__content"><i class="fa fa-share-alt"></i></div></button></div><div class="v-menu__content" style="max-height:auto;min-width:0px;max-width:auto;top:12px;left:0px;transform-origin:top right;z-index:0;display:none;"><div class="v-list"><div class="secondary--text"><a class="v-list__tile v-list__tile--link"><div class="v-list__tile__avatar"><div class="v-avatar" style="height:40px;width:40px;"><i class="fa fa-lg fa-copy"></i></div></div><div class="v-list__tile__title">复制链接</div></a></div></div><input type="text" tabindex="-1" aria-hidden="true" value="" class="fake-hide"></div></div></div></nav><main class="v-content" style="padding-top:56px;padding-right:0px;padding-bottom:0px;padding-left:0px;"><div class="v-content__wrap"><div class="container blog-container grid-list-xl align-center"><div class="layout row wrap"><div class="flex mb-3 xs12"><article class="v-card elevation-16 post-card" style="height:undefined;"><div class="v-card__title"><div class="flex xs12"><h2 class="display-1 mb-3">20 Observable Operators - window, windowToggle, groupBy</h2><div class="post-meta"><time datetime="2018-04-29T12:16:12.000Z" class="secondary--text post-time">2018年04月29日</time></div></div></div><div class="v-card__text pt-0 pb-0"><div class="flex xs12"><div class="content custom"><h1 id="_30-天精通-rxjs-20-observable-operators-window-windowtoggle-groupby"><a href="#_30-天精通-rxjs-20-observable-operators-window-windowtoggle-groupby" aria-hidden="true" class="header-anchor">#</a> 30 天精通 RxJS(20): Observable Operators - window, windowToggle, groupBy</h1><p>前几天我们讲完了能把 Higher Order Observable 转成一般的 Observable 的 operators，今天我们要讲能够把一般的 Observable 转成 Higher Order Observable 的 operators。</p><p>其实前端不太有机会用到这类型的 Operators，都是在比较特殊的需求下才会看到，但还是会有遇到的时候。
</p><h2 id="operators"><a href="#operators" aria-hidden="true" class="header-anchor">#</a> Operators</h2><h3 id="window"><a href="#window" aria-hidden="true" class="header-anchor">#</a> window</h3><p>window 是一整个家族，总共有五个相关的 operators</p><ul><li>window</li><li>windowCount</li><li>windowTime</li><li>windowToggle</li><li>windowWhen</li></ul><p>这里我们只介绍 window 跟 windowToggle 这两个方法，其他三个的用法相对都简单很多，大家如果有需要可以再自行到官网查看。</p><p>window 很类似 buffer 可以把一段时间内送出的元素拆出来，只是 buffer 是把元素拆分到数组中变成</p><pre class="language-javascript"><code>Observable<span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">&gt;</span> <span class="token operator">=&gt;</span> Observable<span class="token operator">&lt;</span>Array<span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">&gt;&gt;</span>

</code></pre><p>而 window 则是会把元素拆分出来放到新的 observable 变成</p><pre class="language-javascript"><code>Observable<span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">&gt;</span> <span class="token operator">=&gt;</span> Observable<span class="token operator">&lt;</span>Observable<span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">&gt;&gt;</span>

</code></pre><p>buffer 是把拆分出来的元素放到数组并送出数组；window 是把拆分出来的元素放到 observable 并送出 observable，让我们来看一个例子</p><pre class="language-javascript"><code><span class="token keyword">var</span> click <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>document<span class="token punctuation">,</span> <span class="token string">'click'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> source <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> example <span class="token operator">=</span> source<span class="token punctuation">.</span><span class="token function">window</span><span class="token punctuation">(</span>click<span class="token punctuation">)</span><span class="token punctuation">;</span>

example
  <span class="token punctuation">.</span><span class="token keyword">switch</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 0</span>
<span class="token comment">// 1</span>
<span class="token comment">// 2</span>
<span class="token comment">// 3</span>
<span class="token comment">// 4</span>
<span class="token comment">// 5 ...</span>

</code></pre><p>首先 window 要传入一个 observable，每当这个 observable 送出元素时，就会把正在处理的 observable 所送出的元素放到新的 observable 中并送出，这里看 Marble Diagram 会比较好解释</p><pre class="language-javascript"><code>click  <span class="token punctuation">:</span> <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span>c<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span>c<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span>c<span class="token operator">--</span>
source <span class="token punctuation">:</span> <span class="token operator">--</span><span class="token operator">--</span><span class="token number">0</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">1</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">2</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">3</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">4</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">5</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">6</span><span class="token operator">--</span><span class="token operator">-</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
                    <span class="token function">window</span><span class="token punctuation">(</span>click<span class="token punctuation">)</span>
example<span class="token punctuation">:</span> o<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span>o<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span>o<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span>o<span class="token operator">--</span>
         \          \          \
          <span class="token operator">--</span><span class="token operator">-</span><span class="token number">0</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">1</span><span class="token operator">-</span><span class="token operator">|</span><span class="token operator">--</span><span class="token number">2</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">3</span><span class="token operator">--</span><span class="token operator">|</span><span class="token operator">-</span><span class="token number">4</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">5</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">6</span><span class="token operator">|</span>
                    <span class="token keyword">switch</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
       <span class="token punctuation">:</span> <span class="token operator">--</span><span class="token operator">--</span><span class="token number">0</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">1</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">2</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">3</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">4</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">5</span><span class="token operator">--</span><span class="token operator">--</span><span class="token number">6</span><span class="token operator">--</span><span class="token operator">-</span><span class="token operator">...</span> 

</code></pre><p>这里可以看到 example 变成发送 observable 会在每次 click 事件发送出来后结束，并继续下一个 observable，这里我们用 switch 才把它摊平。</p><p>当然这个范例只是想单存的表达 window 的作用，没什么太大的意义，实务上 window 会搭配其他的 operators 使用，例如我们想计算一秒钟内触发了几次 click 事件</p><pre class="language-javascript"><code><span class="token keyword">var</span> click <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>document<span class="token punctuation">,</span> <span class="token string">'click'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> source <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> example <span class="token operator">=</span> click<span class="token punctuation">.</span><span class="token function">window</span><span class="token punctuation">(</span>source<span class="token punctuation">)</span>

example
  <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>innerObservable <span class="token operator">=&gt;</span> innerObservable<span class="token punctuation">.</span><span class="token function">count</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token keyword">switch</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>

</code></pre><p><a href="https://jsbin.com/fudocigewi/4/edit?html,js,output" target="_blank" rel="noopener noreferrer">JSBin</a> | <a href="https://jsfiddle.net/sy1fybre/3/" target="_blank" rel="noopener noreferrer">JSFiddle</a></p><p>注意这里我们把 source 跟 click 对调了，并用到了 observable 的一个方法 <code>count()</code>，可以用来取得 observable 总共送出了几个元素，用 Marble Diagram 表示如下</p><pre class="language-text"><code>source : ---------0---------1---------2--...
click  : --cc---cc----c-c----------------...
                    window(source)
example: o--------o---------o---------o--..
         \        \         \         \
          -cc---cc|---c-c---|---------|--..
                    count()
       : o--------o---------o---------o--
         \        \         \         \
          -------4|--------2|--------0|--..
                    switch()
       : ---------4---------2---------0--... 

</code></pre><p>从 Marble Diagram 中可以看出来，我们把部分元素放到新的 observable 中，就可以利用 Observable 的方法做更灵活的操作</p><h2 id="windowtoggle"><a href="#windowtoggle" aria-hidden="true" class="header-anchor">#</a> windowToggle</h2><p>windowToggle 不像 window 只能控制内部 observable 的结束，windowToggle 可以传入两个参数，第一个是开始的 observable，第二个是一个 callback 可以回传一个结束的 observable，让我们来看范例</p><pre class="language-javascript"><code><span class="token keyword">var</span> source <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> mouseDown <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>document<span class="token punctuation">,</span> <span class="token string">'mousedown'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> mouseUp <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>document<span class="token punctuation">,</span> <span class="token string">'mouseup'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> example <span class="token operator">=</span> source
  <span class="token punctuation">.</span><span class="token function">windowToggle</span><span class="token punctuation">(</span>mouseDown<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> mouseUp<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token keyword">switch</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

example<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>

</code></pre><p><a href="https://jsbin.com/fudocigewi/3/edit?html,js,output" target="_blank" rel="noopener noreferrer">JSBin</a> | <a href="https://jsfiddle.net/sy1fybre/2/" target="_blank" rel="noopener noreferrer">JSFiddle</a></p><p>一样用 Marble Diagram 会比较好解释</p><pre class="language-text"><code>source   : ----0----1----2----3----4----5--...

mouseDown: -------D------------------------...
mouseUp  : ---------------------------U----...

        windowToggle(mouseDown, () =&gt; mouseUp)

         : -------o-------------------------...
                  \
                   -1----2----3----4--|
                   switch()
example  : ---------1----2----3----4---------...                                     

</code></pre><p>从 Marble Diagram 可以看得出来，我们用 windowToggle 拆分出来内部的 observable 始于 mouseDown 终于 mouseUp。</p><h3 id="groupby"><a href="#groupby" aria-hidden="true" class="header-anchor">#</a> groupBy</h3><p>最后我们来讲一个开发上比较常用的 operators - groupBy，它可以帮我们把相同条件的元素拆分成一个 Observable，其实就跟平常在 SQL 下是一样个概念，我们先来看个简单的例子</p><pre class="language-javascript"><code><span class="token keyword">var</span> source <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">300</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">take</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> example <span class="token operator">=</span> source
              <span class="token punctuation">.</span><span class="token function">groupBy</span><span class="token punctuation">(</span>x <span class="token operator">=&gt;</span> x <span class="token operator">%</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

example<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// GroupObservable { key: 0, ...}</span>
<span class="token comment">// GroupObservable { key: 1, ...}</span>

</code></pre><p><a href="https://jsbin.com/fudocigewi/1/edit?html,js,console" target="_blank" rel="noopener noreferrer">JSBin</a> | <a href="https://jsfiddle.net/sy1fybre/1/" target="_blank" rel="noopener noreferrer">JSFiddle</a></p><p>上面的例子，我们传入了一个 callback function 并回传 groupBy 的条件，就能区分每个元素到不同的 Observable 中，用 Marble Diagram 表示如下</p><pre class="language-text"><code>source : ---0---1---2---3---4|
             groupBy(x =&gt; x % 2)
example: ---o---o------------|
            \   \
            \   1-------3----|
            0-------2-------4|

</code></pre><p>在实际上，我们可以拿 groupBy 做完元素的区分后，再对 inner Observable 操作，例如下面这个例子我们将每个人的分数作加总再送出</p><pre class="language-javascript"><code><span class="token keyword">var</span> people <span class="token operator">=</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">'Anna'</span><span class="token punctuation">,</span> score<span class="token punctuation">:</span> <span class="token number">100</span><span class="token punctuation">,</span> subject<span class="token punctuation">:</span> <span class="token string">'English'</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">'Anna'</span><span class="token punctuation">,</span> score<span class="token punctuation">:</span> <span class="token number">90</span><span class="token punctuation">,</span> subject<span class="token punctuation">:</span> <span class="token string">'Math'</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">'Anna'</span><span class="token punctuation">,</span> score<span class="token punctuation">:</span> <span class="token number">96</span><span class="token punctuation">,</span> subject<span class="token punctuation">:</span> <span class="token string">'Chinese'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> 
    <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">'Jerry'</span><span class="token punctuation">,</span> score<span class="token punctuation">:</span> <span class="token number">80</span><span class="token punctuation">,</span> subject<span class="token punctuation">:</span> <span class="token string">'English'</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">'Jerry'</span><span class="token punctuation">,</span> score<span class="token punctuation">:</span> <span class="token number">100</span><span class="token punctuation">,</span> subject<span class="token punctuation">:</span> <span class="token string">'Math'</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">'Jerry'</span><span class="token punctuation">,</span> score<span class="token punctuation">:</span> <span class="token number">90</span><span class="token punctuation">,</span> subject<span class="token punctuation">:</span> <span class="token string">'Chinese'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> 
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> source <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token keyword">from</span><span class="token punctuation">(</span>people<span class="token punctuation">)</span>
						   <span class="token punctuation">.</span><span class="token function">zip</span><span class="token punctuation">(</span>
						     Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">300</span><span class="token punctuation">)</span><span class="token punctuation">,</span> 
						     <span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> x<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> example <span class="token operator">=</span> source
  <span class="token punctuation">.</span><span class="token function">groupBy</span><span class="token punctuation">(</span>person <span class="token operator">=&gt;</span> person<span class="token punctuation">.</span>name<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>group <span class="token operator">=&gt;</span> group<span class="token punctuation">.</span><span class="token function">reduce</span><span class="token punctuation">(</span><span class="token punctuation">(</span>acc<span class="token punctuation">,</span> curr<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">(</span><span class="token punctuation">{</span> 
	    name<span class="token punctuation">:</span> curr<span class="token punctuation">.</span>name<span class="token punctuation">,</span>
	    score<span class="token punctuation">:</span> curr<span class="token punctuation">.</span>score <span class="token operator">+</span> acc<span class="token punctuation">.</span>score 
	<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
	<span class="token punctuation">.</span><span class="token function">mergeAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

example<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// { name: &quot;Anna&quot;, score: 286 }</span>
<span class="token comment">// { name: 'Jerry', score: 270 }</span>

</code></pre><p><a href="https://jsbin.com/fudocigewi/2/edit?html,js,console" target="_blank" rel="noopener noreferrer">JSBin</a> | <a href="https://jsfiddle.net/sy1fybre/" target="_blank" rel="noopener noreferrer">JSFiddle</a></p><p>这里我们范例是想把 Jerry 跟 Anna 的分数个别作加总，画成 Marble Diagram 如下</p><pre class="language-text"><code>source : --o--o--o--o--o--o|

  groupBy(person =&gt; person.name)

       : --i--------i------|
           \        \
           \         o--o--o|
            o--o--o--|

	   map(group =&gt; group.reduce(...))

       : --i---------i------|
           \         \
           o|        o|

             mergeAll()
example: --o---------o------|           

</code></pre><h2 id="今日小结"><a href="#今日小结" aria-hidden="true" class="header-anchor">#</a> 今日小结</h2><p>今天讲了两个可以把元素拆分到新的 observable 的 operators，这两个 operators 在前端比较少用到，但在后端或是比较复杂了前端应用才比较有机会用到。不知道读者有没有收获呢？ 如果有任何问题欢迎留言给我，谢谢。</p></div></div></div><div class="v-card__actions"><div class="flex xs12"><a href="/BLOG/tags/RXJS"><span tabindex="0" class="v-chip capitalize chip-tag v-chip--label v-chip--small"><span class="v-chip__content">RXJS</span></span></a></div></div></article></div><div class="flex text-xs-left xs6"><a href="/BLOG/posts/rxjs21.html" class="post-nav v-btn v-btn--flat v-btn--router"><div class="v-btn__content"><div class="grey--text"><i class="fa mr-1 fa-chevron-left"></i>Prev</div><div class="title mt-1 primary--text hidden-xs-only">21 深入 Observable</div></div></a></div><div class="flex text-xs-right xs6"><a href="/BLOG/posts/rxjs19.html" class="post-nav v-btn v-btn--flat v-btn--router"><div class="v-btn__content"><div class="grey--text">Next
          <i class="fa ml-1 fa-chevron-right"></i></div><div class="title mt-1 primary--text hidden-xs-only">19 实际示例 - 简单 Auto Complete 实例</div></div></a></div><div class="flex mt-3 xs12"><div class="v-card" style="height:undefined;"><div class="v-card__title"><span class="headline">Comment</span></div></div></div></div></div><footer class="v-footer blog-footer darken-1 mt-3 theme--dark" style="height:auto;"><div class="primary--text text--lighten-4 text-xs-center py-3 v-card v-card--flat v-card--tile primary" style="height:undefined;"><div class="v-card__text pb-0">博客内容遵循 <a rel="license noopener noreferrer" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank">知识共享 署名 - 非商业性 - 相同方式共享 4.0 国际协议</a></div><div class="v-card__text pt-0 mt-1"><span>訾绍飞 © 2015 - 2018</span><span><!---->
        Power by
        <a href="https://vuepress.vuejs.org" target="_blank" rel="noopener noreferrer">VuePress</a> Theme
        <a href="https://github.com/ShaofeiZi/BLOG" target="_blank" rel="noopener noreferrer">indigo</a></span></div></div></footer></div></main><button type="button" class="v-btn v-btn--bottom v-btn--floating v-btn--fixed v-btn--right accent" style="display:none;"><div class="v-btn__content"><i class="fa fa-lg fa-chevron-up"></i></div></button></div></div></div>
    <script src="/BLOG/assets/js/14.5d9fcbf2.js" defer></script><script src="/BLOG/assets/js/app.1a725be8.js" defer></script>
  </body>
</html>
